<template>
<div class="gj-loadmore">
  <div class="gj-loadmore-content" :class="{ 'is-dropped': topDropped }" :style="{ 'transform': 'translate3d(0, ' + translate + 'px, 0)' }">
    <slot name="top">
      <div class="gj-loadmore-top" v-if="topMethod">
        <div v-show="topStatus == 'pull' || topStatus == 'drop'">
          <div class="imgBox">
            <svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="34px" height="34px" viewBox="0 0 40 40" enable-background="new 0 0 40 40" xml:space="preserve">
              <circle cx = '20.8' cy = '19.5' r = '13.5' stroke = '#f6f6f6' stroke-width = '1.4' fill = 'none'></circle>
              <circle cx = '20.8' cy = '19.5' r = '13.5' stroke = '#BCCAD9' stroke-width = '1.4' fill = 'none' transform = 'matrix(0,-1,1,0,1,40)' :stroke-dasharray = 'strokeDash'></circle>
            </svg>
            <img src="../../assets/images/loading.png" alt="">
          </div>
          <div class="w-loadmore-text pushDownText">{{ topText }}</div>
        </div>

        <div v-show="topStatus === 'loading'" class="loadingText">
          <div class="imgBox">
            <svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="34px" height="34px" viewBox="0 0 40 40" enable-background="new 0 0 40 40" xml:space="preserve">
              <circle cx = '20.8' cy = '19.5' r = '13.5' stroke = '#BCCAD9' stroke-width = '1.4' fill = 'none'></circle>
              <path fill="#f6f6f6" d="M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0
                C22.32,8.481,24.301,9.057,26.013,10.047z">
                <animateTransform attributeType="xml"
                  attributeName="transform"
                  type="rotate"
                  from="0 20 20"
                  to="360 20 20"
                  dur="0.8s"
                  repeatCount="indefinite"/>
                </path>
            </svg>
            <img src="../../assets/images/done.png" alt="">
          </div>

          <div class="w-loadmore-text pushDownText">{{ topText }}</div>
        </div>
      </div>
    </slot>
    <slot></slot>
    <slot name="bottom">
      <div class="gj-loadmore-bottom" v-if="bottomMethod">
        <!-- <div v-show="bottomStatus === 'loading'">
          <svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="40px" height="40px" viewBox="0 0 40 40" enable-background="new 0 0 40 40" xml:space="preserve">
            <path opacity="0.2" fill="#fb8a3f" d="M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946
              s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634
              c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z"/>
            <path fill="#fb8a3f" d="M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0
              C22.32,8.481,24.301,9.057,26.013,10.047z">
              <animateTransform attributeType="xml"
                attributeName="transform"
                type="rotate"
                from="0 20 20"
                to="360 20 20"
                dur="0.5s"
                repeatCount="indefinite"/>
              </path>
            </svg>
        </div> -->
        <span class="w-loadmore-text">{{ bottomText }}</span>
      </div>
    </slot>
  </div>
</div>
</template>

<style>
.gj-loadmore {
  font-size: 24px;
}

.gj-loadmore-content.is-dropped {
  -webkit-transition: .2s;
  transition: .2s;
}

.gj-loadmore-top {
  text-align: center;
  height: 80px;
  /*height: 700px;*/
  /*line-height: 50px;*/
}

.gj-loadmore-bottom {
  text-align: center;
  margin-top: 20px;
}

.gj-loadmore-top {
  margin-top: -80px;
}

.gj-loadmore-bottom {
  margin-bottom: 40px;
}

.gj-loadmore-text {
  vertical-align: middle;
}

.w-loadmore-text {
  color: #999;
}

.loading-icon {
  height: 60px;
  width: 60px;
}

.loadingImg {
  display: inline-block;
  width: 70px;
}

.img {
  display: inline-block;
  width: 50px;
  vertical-align: middle;
}


.imgBox {
  display: inline-block;
  position: relative;
}

.imgBox svg {
  display: inline-block;
  vertical-align: middle;
}




/*.imgBox img {
  display: inline-block;
  width: 36px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}*/

.imgBox img {
  display: inline-block;
  width: 42px;
  vertical-align: middle;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.pushDownText {
  display: inline-block;
  width: 200px;
  text-align: left;
  font-size: 28px;
  margin-left: 20px;
  font-family: '微软雅黑';
}

circle {
  transition: stroke-dasharray .25s;
}
</style>

<script type="text/babel">
export default {
  name: 'gj-loadmore',
  props: {
    maxDistance: {
      type: Number,
      default: 0
    },
    autoFill: {
      type: Boolean,
      default: true
    },
    distanceIndex: {
      type: Number,
      default: 2
    },
    topPullText: {
      type: String,
      default: '下拉即可刷新'
    },
    topDropText: {
      type: String,
      default: '释放即可刷新'
    },
    topLoadingText: {
      type: String,
      default: '加载中...'
    },
    topAllLoadedText: {
      type: String,
      default: '加载完成'
    },
    topDistance: {
      type: Number,
      default: 30
    },
    topMethod: {
      type: Function
    },
    bottomPullText: {
      type: String,
      default: '上拉加载更多'
    },
    bottomLoadingText: {
      type: String,
      default: '加载中...'
    },
    bottomAllLoadedText: {
      type: String,
      default: '已全部加载'
    },
    bottomDistance: {
      type: Number,
      default: 80
    },
    bottomMethod: {
      type: Function
    },
    allowLoad: {
      type: Boolean,
      default: true
    }
  },

  data() {
    return {
      translate: 0,
      scrollEventTarget: null,
      containerFilled: false,
      topText: '',
      topDropped: false,
      bottomText: '',
      // bottomReached: false,
      direction: '',
      startY: 0,
      startScrollTop: 0,
      currentY: 0,
      topStatus: '',
      pushStatus: '',
      bottomStatus: '',
      bottomAllLoaded: false,
      marginBottom: '60px',
      judge: 'block',
      strokeDash: '0 100'
    };
  },

  watch: {
    topStatus(val) {
      this.$emit('top-status-change', val);
      switch (val) {
        case 'pull':
          this.topText = this.topPullText;
          break;
        case 'drop':
          this.topText = this.topDropText;
          break;
        case 'loading':
          this.topText = this.topLoadingText;
          break;
      }
    },
    bottomStatus(val) {
      this.$emit('bottom-status-change', val);

      switch (val) {
        case 'pull':
          this.bottomText = this.bottomPullText;
          break;
        case 'done':
          this.bottomText = this.bottomAllLoadedText;
          break;
        case 'loading':
          this.bottomText = this.bottomLoadingText;
          break;
      }
    }
  },

  methods: {
    onTopLoaded() {
      // let time = String(new Date()).split(' ');
      // console.log(time);
      setTimeout(() => {
        this.topStatus = 'loadingDone';
        this.translate = 0;
        this.strokeDash = '0 100';
      }, 800);
    },

    onBottomLoaded() {
      this.bottomStatus = 'pull';

      if (!this.bottomAllLoaded && !this.containerFilled) {
        this.fillContainer();
      }
    },

    onBottomAllLoaded() {
      this.bottomStatus = 'done';
      this.bottomAllLoaded = true;
      this.bottomText = this.bottomAllLoadedText;
    },

    onBottomError(text) { // 错误或数据为空时可调此方法用来隐藏底部牛头
      this.bottomStatus = 'error';
      this.bottomAllLoaded = true;
      this.bottomText = text || '';
    },

    reset() {
      this.$nextTick(() => {
        this.bottomAllLoaded = false;
        this.init();
      });
    },

    getScrollEventTarget(element) {
      let currentNode = element;
      while (currentNode && currentNode.tagName !== 'HTML' &&
        currentNode.tagName !== 'BODY' && currentNode.nodeType === 1) {
        let overflowY = document.defaultView.getComputedStyle(currentNode).overflowY;
        if (overflowY === 'scroll' || overflowY === 'auto') {
          return currentNode;
        }
        currentNode = currentNode.parentNode;
      }
      return window;
    },

    getScrollTop(element) {
      if (element === window) {
        return Math.max(window.pageYOffset || 0, document.documentElement.scrollTop);
      } else {
        return element.scrollTop;
      }
    },

    bindTouchEvents() {
      var vm = this;

      this.scrollEventTarget.addEventListener('touchstart', this.handleTouchStart);
      this.scrollEventTarget.addEventListener('touchmove', this.handleTouchMove);
      this.scrollEventTarget.addEventListener('touchend', this.handleTouchEnd);
      this.scrollEventTarget.addEventListener('scroll', this.handleScroll);
    },

    init() {
      // this.topStatus = 'pull';
      this.bottomStatus = 'pull';
      this.topText = this.topPullText;
      this.scrollEventTarget = this.getScrollEventTarget(this.$el);

      if (typeof this.bottomMethod === 'function') {
        this.fillContainer();
        this.bindTouchEvents();
      }
      if (typeof this.topMethod === 'function') {
        this.bindTouchEvents();
      }
    },

    fillContainer() {
      if (this.autoFill) {
        this.$nextTick(() => {
          if (this.scrollEventTarget === window) {
            this.containerFilled = this.$el.getBoundingClientRect().bottom + 1 >=
              document.body.scrollHeight;
          } else {
            this.containerFilled = this.$el.getBoundingClientRect().bottom >=
              this.scrollEventTarget.getBoundingClientRect().bottom;
          }
          if (!this.containerFilled) {
            this.bottomStatus = 'loading';
            this.bottomMethod();
          }
        });
      }
    },

    checkBottomReached() {
      if (this.scrollEventTarget === window) {
        return document.body.scrollTop + document.documentElement.clientHeight >= document.body.scrollHeight;
      } else {
        return this.$el.getBoundingClientRect().bottom <= this.scrollEventTarget.getBoundingClientRect().bottom + 1;
      }
    },

    handleTouchStart(event) {
      this.startY = event.touches[0].clientY;
      this.startScrollTop = this.getScrollTop(this.scrollEventTarget);

      if (this.topStatus !== 'loading') {
        this.topStatus = 'pull';
        this.topDropped = false;
      }
    },

    handleTouchMove(event) {
      if (this.startY < this.$el.getBoundingClientRect().top && this.startY > this.$el.getBoundingClientRect().bottom) {
        return;
      }

      this.currentY = event.touches[0].clientY;
      let distance = (this.currentY - this.startY) / this.distanceIndex;

      let perimeter = Math.PI * 2 * 14,
        percent = event.touches[0].clientY / 380;
      this.strokeDash = perimeter * percent + ' ' + perimeter * (1 - percent);
      this.direction = distance > 0 ? 'down' : 'up';
      if (typeof this.topMethod === 'function' && this.direction === 'down' &&
        this.getScrollTop(this.scrollEventTarget) === 0 && this.topStatus !== 'loading') {
        event.preventDefault();
        event.stopPropagation();
        if (this.maxDistance > 0) {
          this.translate = distance <= this.maxDistance ? distance - this.startScrollTop : this.translate;
        } else {
          this.translate = distance - this.startScrollTop;
        }
        if (this.translate < 0) {
          this.translate = 0;
        }
        this.topStatus = this.translate >= this.topDistance + 55 ? 'drop' : 'pull';
        if (this.translate < this.topDistance) {
          this.topStatus = ''
        }
        this.$emit('translate-change', this.translate);
      }
    },

    handleTouchEnd() {
      if (this.direction === 'down' && this.getScrollTop(this.scrollEventTarget) === 0 && this.translate > 0) {
        this.topDropped = true;
        this.strokeDash = '0 100';
        if (this.topStatus === 'drop') {
          this.translate = '70';
          this.topStatus = 'loading';
          this.topMethod();
        } else {
          this.translate = '0';
          this.topStatus = 'pull';
        }
      }
      this.$emit('translate-change', this.translate);
      this.direction = '';
    },

    handleScroll(event) {
      var vm = this;
      if (!vm.allowLoad) return;

      this.$nextTick(function() {
        var bottomReached = vm.checkBottomReached();
        if (typeof this.bottomMethod === 'function' && this.bottomStatus !== 'loading' && !this.bottomAllLoaded && bottomReached) {
          event.preventDefault();
          event.stopPropagation();

          this.bottomStatus = 'loading';
          this.bottomMethod();
        }
      })
    }
  },

  mounted() {
    this.init();
  },

  beforeDestroy() {
    this.scrollEventTarget.removeEventListener('touchstart', this.handleTouchStart);
    this.scrollEventTarget.removeEventListener('touchmove', this.handleTouchMove);
    this.scrollEventTarget.removeEventListener('touchend', this.handleTouchEnd);
    this.scrollEventTarget.removeEventListener('scroll', this.handleScroll);
  }
};
</script>
